#include "DataQuick.h"
#include <QLineEdit>
#include <QComboBox>
#include <QPlainTextEdit>

#include "../Utility/XXlogger.h"

#define kQLineEdit "QLineEdit"
#define kQComboBox "QComboBox"
#define kQPlainTextEdit "QPlainTextEdit"

typedef QPair<QString,QString> StringPair;

void DataQuick::config(const QString &key, QObject *object){
    _keyInfo[key] = StringPair(object->objectName(),object->metaObject()->className());
}
void DataQuick::config(const QString &key, const QString &objName, const QString &clsName){
    _keyInfo[key] = StringPair(objName,clsName);
}

void DataQuick::set(QWidget *widget, QVariantMap data){
    for (auto iter=_keyInfo.begin(); iter!=_keyInfo.end(); iter++) {
        QString objName = iter.value().first;
        QString clsName = iter.value().second;
        QVariant value = data[iter.key()];

        findObjectAndSet(widget, objName, clsName, value);
    }
}
QVariantMap DataQuick::get(QWidget *widget){
    QVariantMap data;
    for (auto iter=_keyInfo.begin(); iter!=_keyInfo.end(); iter++) {
        QString objName = iter.value().first;
        QString clsName = iter.value().second;
        QVariant value;

        if(!findObjectAndGet(widget, objName, clsName, value)){
            continue;
        }
        data[iter.key()] = value;
    }
    return data;
}

QWidget* DataQuick::findObjectDirectly(QWidget *widget, const QStringList &objNames){
    for(int index=0; index<objNames.count()-1; index++){
        widget = widget->findChild<QWidget*>(objNames[index]);
        if(nullptr == widget){
            return widget;
        }
    }
    return widget;
}
void DataQuick::findObjectAndSet(QWidget *widget, const QString &objName, const QString &clsName, const QVariant &data){
    if(clsName == kQLineEdit)  {
        QLineEdit *lineEdit = findObject<QLineEdit>(widget,objName);
        if(lineEdit){
            lineEdit->setText(data.toString());
        }
        else{
            goto FailureToFindObject;
        }
    }
    else if(clsName == kQComboBox)  {
        QComboBox *comboBox = findObject<QComboBox>(widget,objName);
        if(comboBox){
            comboBox->setCurrentText(data.toString());
        }
        else{
            goto FailureToFindObject;
        }
    }
    else if(clsName == kQPlainTextEdit)  {
        QPlainTextEdit *plainTextEdit = findObject<QPlainTextEdit>(widget,objName);
        if(plainTextEdit){
            plainTextEdit->setPlainText(data.toString());
        }
        else{
            goto FailureToFindObject;
        }
    }
    else {
        xxLogStr(QString("unknown clsName. clsName：%1").arg(clsName));
    }
    return;

FailureToFindObject:
    xxLogStr(QString("could not find object. objName:%1 clsName:%2").arg(objName).arg(clsName));
}
bool DataQuick::findObjectAndGet(QWidget *widget, const QString &objName, const QString &clsName, QVariant &data){
    if(clsName == kQLineEdit){
        QLineEdit *lineEdit = findObject<QLineEdit>(widget,objName);
        if(lineEdit){
            data = lineEdit->text();
        }
        else{
            goto FailureToFindObject;
        }
    }
    else if(clsName == kQComboBox)  {
        QComboBox *comboBox = findObject<QComboBox>(widget,objName);
        if(comboBox){
            data = comboBox->currentText();
        }
        else{
            goto FailureToFindObject;
        }
    }
    else if(clsName == kQPlainTextEdit)  {
        QPlainTextEdit *plainTextEdit = findObject<QPlainTextEdit>(widget,objName);
        if(plainTextEdit){
            data = plainTextEdit->toPlainText();
        }
        else{
            goto FailureToFindObject;
        }
    }
    else {
        xxLogStr(QString("unknown clsName. clsName：%1").arg(clsName));
        return false;
    }
    return true;

FailureToFindObject:
    xxLogStr(QString("could not find object. objName:%1 clsName：%2").arg(objName).arg(clsName));
    return false;
}

template<class T>
T* DataQuick::findObject(QWidget *widget, const QString &objName){
    if(objName.contains('.')){
        QStringList objNames = objName.split(".");
        QWidget *target = findObjectDirectly(widget,objNames);
        if(target){
            return target->findChild<T*>(objNames.last());
        }
        else {
            return nullptr;
        }
    }
    else{
        return widget->findChild<T*>(objName);
    }
}
